// $URL: http://mingw-lib.googlecode.com/svn/trunk/working/avcodec_to_widget_8/t_youtube.cpp $
// $Rev: 283 $
// $Author: akio.miyoshi $
// $Date:: 2010-07-26 11:45:02 +0000#$

#include "t_youtube.h"
#include "nbr.h"

T_Youtube::T_Youtube(QNetworkAccessManager *a_nam)
    //: m_own_nam(false)
{
    if(a_nam)
    {
        m_nam = a_nam;
        m_own_nam = false;
    }
    else
    {
        m_nam = new QNetworkAccessManager();
        m_own_nam = true;
    }
}

T_Youtube::~T_Youtube()
{
    if(m_own_nam)
    {
        delete m_nam;
    }
}

QByteArray T_Youtube::batchGet(const QString &a_url)
{
    NetworkBatch v_nbat(m_nam);
    QNetworkReply *v_reply = v_nbat.get(a_url);
    return v_reply->readAll();
}

QUrl T_Youtube::getVideoStreamUrl(QString a_id, int a_fmt)
{
    QMap<int, QUrl> v_fmt_map;
    //[Get Token & Stream Map]
    //QString v_token = getTokenForVideoStreamDetail(a_id, v_fmt_map);
    QString v_token = getTokenForVideoStreamEmbed(a_id, v_fmt_map);
    if(v_token == "")
    {
        //v_token = getTokenForVideoStreamEmbed(a_id, v_fmt_map);
        v_token = getTokenForVideoStreamDetail(a_id, v_fmt_map);
    }
    qDebug() << "[v_token(getVideoStreamUrl)]" << v_token;
    qDebug() << "[v_fmt_map.keys()]" << v_fmt_map.keys();
    QUrl v_url("http://www.youtube.com/get_video");
    v_url.addQueryItem("video_id", a_id);
    v_url.addQueryItem("t", v_token);
    v_url.addQueryItem("el", "detailpage");
    v_url.addQueryItem("ps", "");
    v_url.addQueryItem("fmt", QString::number(a_fmt));
    v_url.addQueryItem("asv", "2");
    //v_url.addQueryItem("noflv", "1");
    return v_url;
}


QString T_Youtube::getVideoStreamMap(QString a_id, QMap<int, QUrl> &a_fmt_map)
{
    //[Get Token & Stream Map]
    //QString v_token = getTokenForVideoStreamEmbed(a_id, a_fmt_map);
    QString v_token = getTokenForVideoStreamDetail(a_id, a_fmt_map);
    if(v_token == "")
    {
        //v_token = getTokenForVideoStreamDetail(a_id, a_fmt_map);
        v_token = getTokenForVideoStreamEmbed(a_id, a_fmt_map);
    }
    qDebug() << "[v_token(getVideoStreamMap)]" << v_token;
    qDebug() << "[a_fmt_map.keys()]" << a_fmt_map.keys();
    return v_token;
}

QString T_Youtube::getTokenForVideoStreamEmbed(QString a_id, QMap<int, QUrl> &a_fmt_map)
{
    //[Get Token]
    QString v_url_1 =
            QString("http://www.youtube.com/get_video_info?&video_id=%1&el=embedded&ps=default")
            //QString("http://www.youtube.com/get_video_info?&video_id=%1&el=detailpage&ps=&noflv=1")
            .arg(a_id);
    ////QByteArray v_params_1 = NetworkThreadRequest::doGet2(v_url_1);
    QByteArray v_params_1 = this->batchGet(v_url_1);
    v_params_1.prepend("?");
    QUrl v_params_2;
    v_params_2.setEncodedUrl(v_params_1);
    QString v_status = v_params_2.queryItemValue("status");
    QString v_reason = v_params_2.queryItemValue("reason");
    QString v_token = v_params_2.queryItemValue("token");
    QString v_allow_embed = v_params_2.queryItemValue("allow_embed");
    QString v_fmt_stream_map = v_params_2.queryItemValue("fmt_stream_map");
    //qDebug() << v_status << v_allow_embed << v_token << v_fmt_stream_map;
    if(v_status == "fail")
    {
        //QMessageBox::information(0, "fail", v_reason);
        //g_Env->showMessage(v_reason);
        qDebug() << "[v_reason]" << v_reason;
    }
    else
    {
        //g_Env->showMessage("");
    }
    if(v_token == "")
    {
        qDebug() << v_params_2;
    }
    a_fmt_map.clear();
    if(v_fmt_stream_map != "")
    {
        QStringList v_slist_1 = v_fmt_stream_map.split(',');
        for(int i=0; i<v_slist_1.size(); i++)
        {
            QStringList v_slist_2 = v_slist_1.at(i).split('|');
            int v_fmt = v_slist_2.at(0).toInt();
            QString v_stream_url_1 = v_slist_2.at(1);
            QUrl v_stream_url_2;
            v_stream_url_2.setEncodedUrl(v_stream_url_1.toLatin1());
            a_fmt_map.insert(v_fmt, v_stream_url_2);
        }
    }
    qDebug() << "[v_token(embed)]" << v_token;
    qDebug() << "[a_fmt_map.keys()]" << a_fmt_map.keys();
    return v_token;
}

QString T_Youtube::getTokenForVideoStreamDetail(QString a_id, QMap<int, QUrl> &a_fmt_map)
{
    QString v_watch_url =
            QString("http://www.youtube.com/watch?v=%1")
            .arg(a_id);
    qDebug() << "[v_watch_url]" << v_watch_url;
    QByteArray v_html_raw = this->batchGet(v_watch_url);
    //qDebug() << "[v_html_raw]" << v_html_raw;
    //qDebug() << "[v_html_raw.size()]" << v_html_raw.size();
    QString v_html_str = QString::fromUtf8(v_html_raw);
    //qDebug() << "[v_html_str]" << v_html_str;

    int v_pos = 0;

    QRegExp v_rxStream("[?&](fmt_stream_map=[^&'\"\\\\]+)");
    v_pos = v_rxStream.indexIn(v_html_str, 0);
    a_fmt_map.clear();
    if(v_pos != -1)
    {
        QByteArray v_params_raw = v_rxStream.cap(1).toLatin1();
        v_params_raw.prepend("?");
        QUrl v_params_url;
        v_params_url.setEncodedUrl(v_params_raw);
        QString v_fmt_stream_map = v_params_url.queryItemValue("fmt_stream_map");
        if(v_fmt_stream_map != "")
        {
            QStringList v_slist_1 = v_fmt_stream_map.split(',');
            for(int i=0; i<v_slist_1.size(); i++)
            {
                QStringList v_slist_2 = v_slist_1.at(i).split('|');
                int v_fmt = v_slist_2.at(0).toInt();
                QString v_stream_url_1 = v_slist_2.at(1);
                QUrl v_stream_url_2;
                v_stream_url_2.setEncodedUrl(v_stream_url_1.toLatin1());
                a_fmt_map.insert(v_fmt, v_stream_url_2);
            }
        }
    }
    QRegExp v_rxToken("[?&](t=[^&'\"\\\\]+)");
    v_pos = v_rxToken.indexIn(v_html_str, 0);
    qDebug() << "[pos]" << v_pos;
    if(v_pos == -1)
    {
        return "";
    }
    else
    {
        //qDebug() << "cap(0)" << v_rxToken.cap(0);
        //qDebug() << "cap(1)" << v_rxToken.cap(1);
        QByteArray v_params_raw = v_rxToken.cap(1).toLatin1();
        qDebug() << "v_rxToken[v_params_raw]" << v_params_raw;
        v_params_raw.prepend("?");
        QUrl v_params_url;
        v_params_url.setEncodedUrl(v_params_raw);
        QString v_token = v_params_url.queryItemValue("t");
        qDebug() << "[v_token(detail)]" << v_token;
        qDebug() << "[a_fmt_map.keys()]" << a_fmt_map.keys();
        return v_token;
    }
}
